home *** CD-ROM | disk | FTP | other *** search
- APurify
- -------
-
- (c) par Samuel DEVULDER
- Mars 1995
-
- Samuel.Devulder@info.unicaen.fr
-
- DESCRIPTION (COURTE):
- --------------------
- APurify est un programme qui permet de detecter les acces illegaux en
- memoire de vos programmes sans utilisation de dispositif materiel
- exterieur (MMU). Il permet d'eviter un certain nombre de bugs du a
- l'acces a de la memoire non detenue par le programme.
-
- SYNOPSIS:
- --------
- APurify [-revinfo] <Fichier source> [<Fichier destination>]
-
- APurify -revinfo
- Pour avoir les informations concernant APurify (le nom, la taille
- et la date des modules le composant ainsi que le nombre de
- compilations deja effectuees).
-
- APurify <Fichier source> <Fichier destination>
- Analyse le fichier source assembleur et genere une version de ce
- fichier source pret a etre assemblee puis reliee a APur.lib. Les
- acces memoire illegaux de ce fichier source seront detectes par
- APurify. Le fichier destination peut etre identique au fichier
- source.
-
- APurify <Fichier source>
- Idem que: APurify <Fichier source> <Fichier source>. ie: le fichier
- apres purification (:-)) aura le meme nom que le fichier source.
-
- DESCRIPTION (UN PEU PLUS LONGUE):
- --------------------------------
- En regle generale, dans un programme au niveau du microprocesseur,
- il y a deux sorte d'acces a la memoire. Il y a les acces directs et les
- acces indirects en memoire. Par exemple, en C, l'acces direct peut etre
- assimile a l'acces des variables globales. L'acces indirect a l'acces a
- une valeur d'un tableau. Plus precisement, l'acces direct correspond a
- la lecture ou l'ecriture dans une variable dont l'adresse est connue a
- la compilation ou des le chargement du programme en memoire. L'acces
- indirect est utilise pour des variables dont l'adresse et fixee
- dynamiquement par le programme. Par exemple, si p est un pointeur sur
- un tableau alloue par malloc(), *p est un acces indirect. L'acces
- indirect se produit aussi dans le cas d'instructions de la forme T[i]
- ou T est un tableau global. En effet, l'adresse memoire de T[i] n'est
- pas connue par avance. Elle depend de la valeur de l'indice i. C'est
- pourquoi cet element requiert un acces indirect. On parle d'indirection
- lorsqu'il s'agit d'acces indirect a la memoire.
-
- Un programme normal ne doit pas en regle general acceder a de la
- memoire qui ne lui appartient pas. Ce genre d'acces a de la memoire
- peut etre qualifie d'acces illegal.
-
- L'acces direct illegal en memoire est en principe impossible car
- par definition de l'acces direct, seules les variables globales
- peuvent etre accedees ainsi et il est certain que les variables d'un
- programme appartiennent a celui-ci (a part evidement des codes ecrit en
- assembleur expres qui referencent une valeur absolue, comme par
- exemple: btst #6,$bfe001; cependant ce code est impossible a produire
- en C directement). On peut donc considerer que les acces direct en
- memoire ne provoquent pas d'acces illegaux.
-
- En revanche, il est certain que les acces memoire indirects peuvent
- etre illegaux. Il est bien connu qu'un certain nombre de bugs sont dus
- a des debordements des tableaux. Si le debordement est en lecture, ceci
- n'est pas trop grave; mais si le debordement est en ecriture, cela peut
- provoquer de gros plantages.
-
- Apurify, intervient sur ce genre d'acces en verifiant la validite
- des acces memoire par indirection. Apurify garde trace de la memoire
- allouee par le programme et verifie a chaque acces memoire indirect si
- celui-ci est valide. On peut se dire que cela fait beaucoup de test.
- Certes, oui, mais il faut savoir que Apurify n'est pas fait pour etre
- employe en permanence par un programme. Il ne doit servir que dans une
- phase de mise au point. De plus, il faut remarquer qu'en realite, les
- indirections sont tres peu frequentes tout compte fait. En effet, seuls
- les variables liees a des tableaux alloues par malloc() font des vrais
- acces indirects. Ainsi, l'acces aux variables sur la pile, bien
- qu'etant fait par indirection, ne doit pas etre teste puisque ces acces
- sont forcement corrects si la pile n'est pas debordee. De meme en
- modele SMALL_DATA, l'acces aux variables globales se fait par
- indirection. Ces indirections ne sont pas non plus a verifier.
-
- Si un acces indirect est detecte illegal, APurify affiche un
- message d'erreur explicite sur la sortie standard d'erreur du programme
- (admirez la justification complete de la sortie :^). Il y a deux sorte
- d'acces illegaux. Certains acces se font a de la memoire non detenue
- par le programme (APurify parle alors d'acces entre blocks), alors que
- d'autre acces se font a cheval sur un block memoire detenu par le
- programme et un autre non detenu par lui (APurify parle alors de
- debordement de block).
-
- Apurify represente la memoire possedee par le programme sous forme
- de block. Chaque block est affiche suivant le format
-
- [0x<n1>(<n2>) <attr> (<text>)]
-
- ou <n1> est l'adresse hexadecimale du debut de block, <n2> la longueur
- decimale du block, <attr> une suite de 3 caracteres de la forme RWS
-
- ou R = block autorise en lecture
- W = block autorise en ecriture
- S = block systeme (= block pre-existant au programme)
-
- si un des acces est interdit, la lettre '-' remplace le caractere
- correspondant, <text> est le nom de la derniere procedure analysee par
- Apurify apres laquelle le block a ete alloue (en fait il s'agit
- simplement du nom de la procedure dans laquelle le block a ete alloue).
-
- En cas d'erreur, Apurify affiche les blocks entre lesquels l'acces
- memoire est tombe ou le block deborde ainsi de le nombre d'octets de
- depassement de chaque block. Apurify affiche aussi un block pour
- representer la memoire accedee. Dans ce block, le debut du block est
- l'adresse memoire fautive, la longueur est la longeur de l'acces (1
- signifie un acces sur un type char, 2 sur un type short, 4 sur un type
- int/long et >4 pour un acces par movem illegal). Les attributs sont R
- ou W suivant qu'il s'agisse d'un acces en lecture ou en ecriture. Le
- texte, lui, contient le nom de la procedure dans laquelle l'acces
- memoire illegal est intervenu.
-
- APurify detecte aussi la sortie du programme sans desalloction de
- certains blocks memoire. (en fait, il detecte les blocks non desalloues
- lors de la fermeture de la librairie).
-
- Certains blocks memoire pre-existant au programme sont reconnus.
- Ceux-ci sont le premier kilo-octet de memoire qui contient les vecteurs
- d'interruption du 680x0, les differents segments du programme et la
- pile du programme. L'acces a ces portions de memoire ne sera pas
- declare illegal; de meme que la fermeture de la librairie sans leur
- desallocations. Ces blocks sont declares SYSTEME (bit S sur leurs
- attributs).
-
- Les blocks alloues par malloc() et autres AllocMem(), ainsi que les
- blocks alloues indirectement (comme ceux alloues par OpenScreen() et
- autres...) sont pris en compte par APurify. Cependant je dois avouer
- que je n'ai pas encore teste les blocks alloues indirectement.
- Cependant, cela doit marcher (APurify patche les routines systeme
- AllocMem() et FreeMem()). Ainsi un programme peut acceder aux bitplanes
- d'un de ses ecrans sans provoquer d'erreur.
-
- Si un acces memoire tombe dans un block memoire mais que l'attribut
- du block est incompatible avec l'acces, APurify affiche une erreur de
- protection. Pour l'instant, seul le premier kilo-octet est protege
- contre l'ecriture (pour pouvoir lire l'adresse d'Exec). Cependant, a
- l'avenir, il se peut que le block de code soit lui-aussi protege en
- lecture.
-
- En interne, pour accelerer la recherche de block, APurify possede
- un cache des derniers blocks deja accedes. En effet, il est tres
- probable qu'apres l'acces en memoire a un block, les acces suivant se
- feront sur ce block recemment accede. Ainsi, malgres la presence de
- nombreux blocks memoire, l'execution du programme ne doit pas etre
- ralentie de trop. (Cependant, je n'ai pas teste l'efficacite de ce
- cache ...).
-
- USAGE:
- -----
- APurify peut etre vu comme un pre-assembleur. C'est a dire qu'il
- faut l'utiliser sur le source assembleur juste avant la phase
- d'assemblage. Il analyse le fichier qui doit etre assemble et le
- modifie pour tenir compte de APurify.
-
- Le schema normal d'utilisation a partir d'un code C est de:
-
- - compiler les sources C en generant les codes assembleur.
- - lancer APurify sur chacun de ces sources assembleur.
- - linker tous les .o ensembles avec la librairie APur.
-
- Comme on peut le voir, APurify ne necessite pas de modifier le code C
- pour etre utilise. Cependant, il faut ouvrir la librarie par un appel a
- AP_Init() dans le main() et *TRES IMPORTANT* fermer la bibliotheque a
- la sortie du programme (juste avant tous les exit()) par un appel a
- AP_Close(). En effet, etant donne qu'APurify patche les fonctions
- AllocMem() et FreeMem() systeme, si le programme termine sans avoir
- ferme la bibliotheque, le prochain appel a l'une de ces fonctions fera
- apparaitre le guru....(on vous aura prevenu :-).
-
- Si on oublie d'ouvrir la bibliotheque dans le programme, un message
- d'avertissement est affiche et l'execution continue sans l'intervention
- d'APurify.
-
- On peut remarquer qu'APurify peut aussi etre utilise sur tous les
- langages generant un code assembleur intermediaire (y compris
- l'assembleur lui meme :-) ). Il faut aussi noter qu'il est possible
- d'utiliser APurify sur un programme dont on ne possede pas le code
- source (ou les .o sans les .asm correspondants). Il existe en effet
- certains programmes permettant de generer un code assembleur
- recompilable a partir d'un programme executable. A partir d'un tel
- fichier, il suffit de peu de manipulations (ajouter en debut de tous
- les labels le caractere '_' et inserer les appels a AP_Init() et
- AP_Close() aux bons endroits) pour pouvoir utiliser APurify.
-
- En principe, APurify introduit l'appel de fonctions intermediaires
- ainsi que de nouvelle donnees dans le segment de donnees (pour stocker
- le nom des procedures). La syntaxe d'introduction de nouvelles sections
- ainsi que de referencement a des procedures externes varie d'un
- compilateur a l'autre. APurify se debrouille pour determiner quel
- compilateur est utilise en analysant le code. APurify connait les
- pseudo-instructions dseg/dseg, public (AZTEC) et section, xref/xdef
- (DICE, HCC, ...). Si un compilateur connait l'une quelconque de ces
- syntaxe, APurify peut etre utilise avec lui (mais je n'ai teste que
- DICE).
-
- La librairie fournie APur.lib est une librairie pour DICE. Cette
- librairie peut etre utilisee sur d'autres compilateurs acceptant le
- format de cette librairie (format COMMODORE). Cependant, DICE possede
- un symbol specifique pour representer la base de la pile d'un programme
- (variable ULONG *_ExitSP). Si le compilateur choisit pour le linkage ne
- connait pas cette variable, il faut que vous declariez une variable
- globale identique et pointant sur l'adresse de retour du processus sur
- la pile (ie:. 8 octets en dessous de la base de la pile) moins 44
- octets. C'est a dire que _ExitSP doit valoir:
-
- ULONG *_ExitSP = (ULONG *)((char *)Base_Pile_Processus - 8 - 44).
-
- Pourquoi cette formule barabare ? Eh bien, c'est que la base de la pile
- d'un processus n'est pas toujours celle indiquee dand les champs du
- systeme. En fait chaque compilateur possede une variable globale
- pointant sur l'adresse de sortie du processus (celle qui est fournie
- par le systeme sur la pile avant le lancement du processus). Cette
- variable doit etre utilisee par la procedure _exit() du C normalement.
- La base de la pile du processus est alors ce pointeur + 8 octets.
- Maintenant, a vous d'adapter la valeur de _ExitSP en fonction de votre
- compilateur.
-
- Si la libraire n'est pas bonne, vous pouvez la reconstruire. Pour
- cela, compilez APfuncs.c et APserv.a (modifiez-les a votre gout). Puis
- fusionnez-les ensembles pour creer APur.lib.
-
- PARTIE LEGALE:
- -------------
- Ce programme est livre tel quel. Je ne dois pas etre tenu
- responsable pour les mefaits entraines pas l'utilisation de ce logiciel
- (en revanche, je veux bien etre tenu responsable pour les bienfaits
- engendres par ce logiciel :^). Employez ce programme a vos propres
- risques.
-
- Ce programme est freeware. Vous pouvez l'utiliser et le distribuer
- librement a condition de garder l'archive intacte (pas d'alteration des
- fichiers sauf eventuelle compression). Il ne peut etre vendu a mon insu
- (bien qu'une somme modique puisse etre demandee pour le support
- materiel (diskette, CD,...) dans la cas de distribution organisee).
- Toute utilisation commerciale de ce logiciel et toute vente avec
- plus-value doit m'etre demandee par avance. Je garde les droits
- d'auteurs sur ce programme ainsi que sur ses futures versions. Je me
- reserve le droit de modifier ce programme sans en avertir les
- utilisateurs.
-
- Je veux bien que chaque utilisateur de ce logiciel m'envoie une
- carte postale en echange son l'utilisation ou tout autre chose (argent,
- documentation, amiga, ...). Mais ceci n'est pas une obligation :-). Mon
- adresse postale est:
-
- M. DEVULDER Samuel
- 1, Rue du chateau
- 59380 STEENE
- FRANCE
-
- Vous pouvez m'envoyer des suggestions, les bugs decouverts dans le
- logiciel a mon adresse electronique suivante:
-
- devulder@info.unicaen.fr
-
- DISTRIBUTION:
- ------------
- Cette distribution contient les versions francaise et anglaise
- de ce logiciel:
-
- - APurify.eng.do: documention anglaise
- - APurify.fre.doc: cette documentation francaise
-
- _/ - APurify.fre: version francaise de l'analyseur
- | \ - APurify.eng: version anglaise de l'analyseur
- |
- +-----> a renomer en APurify suivant votre choix.
-
- _/ - APur.fre.lib: version francaise de la librairie
- | \ - APur.eng.lib: version anglaise de la librairie
- |
- +-----> a renomer en APur.lib suivant votre choix. Cette librairie est
- au format COMMODORE (generee par DICE).
-
- _/ - APfuncs.c
- | \ - APserv.a
- |
- +-----> pour reconstruire la librairie.
-
- - test.c: source d'un programme de test debile
- - test.fre: programme de test linke avec APur.fre.lib
- - test.eng: programme de test linke avec APur.eng.lib.
-
-
- NOTES:
- -----
- Ma configuration est la suivante: un viel A500 1Mo RAM de 1989, 1
- lecteur de diskette, KS1.3, et beaucoup de patience (ah si j'avais un
- A4000/68040/33Mhz !).
-
- L'idee de ce programme m'a ete donnee apres une discussion avec
- Cedric BEUST (AMIGA NEWS) sur IRC (Internet Relay Chat). Merci Cedric !
-
- Toutes les marques citees sont proprietes de leurs proprietaires
- respectifs.
-
- APurify a ete compile avec netdcc, la version non enregistree de
- DICE, par Matt DILLON.
-
- Le source du scanneur de source assembleur a ete bati a partir de
- l'optimisateur TOP de la distribution HCC ((c) Sozobon ltd, Tony
- Andrews & Detlef Wuerkner).
-
- Il existe un certain nombre de programme realisant a peu pres la
- meme chose que APurify. Par exemple, FORTIFY de Simon P. Bullen, mais
- il ne detecte que les acces en ecriture illegaux sur les bords des
- blocks alloues lors de la liberation des ces blocks. Ainsi il ne
- detecte pas les debordements trop important ainsi que les debordements
- en lecture et la detection n'est pas immediate. Enforcer peut aussi
- detecter les acces illegaux de la memoire, il me semble, mais il fait
- usage d'extensions materielles (MMU).
-
- BUGS:
- ----
- APurify ne connait pas la memoire publique dans laquelle un
- programme peut lire ou ecrire sans l'avoir alloue. Ainsi, il reportera
- une erreur quand un programme accede au contenu d'un message obtenu par
- un GetMsg().
-
- APurify ne sait analyser que le code 68000. Si le source contient
- des instructions 680x0 (x>1), et si ces instructions sont inconnues du
- 68000 (ex: les instructions de champ de bits), elles ne seront pas
- traitee. Si c'est un mode d'adressage inconnu, il reportera un message
- d'erreur. Cependant, ceci peut etre corrige des que j'aurais eu le
- source d'un assembleur 680x0 (x>1) {mais il faut le temps... et vous
- etes bienvenus de me dire si vous en possedez un}.
-
- Sans doute d'autres bugs... j'attend vos rapports.
-
-